package xaj.xc;

import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;

import polyglot.ast.NodeFactory;
import polyglot.frontend.CupParser;
import polyglot.frontend.FileSource;
import polyglot.frontend.GlobalBarrierPass;
import polyglot.frontend.Job;
import polyglot.frontend.Parser;
import polyglot.frontend.Pass;
import polyglot.frontend.VisitorPass;
import polyglot.frontend.Pass.ID;
import polyglot.lex.Lexer;
import polyglot.types.TypeSystem;
import polyglot.util.ErrorQueue;
import xaj.xc.ast.XAJNodeFactory_c;
import xaj.xc.types.XAJTypeSystem_c;
import xaj.xc.visit.DesugarVisitor;

public class ExtensionInfo extends abc.aspectj.ExtensionInfo {

	public static final String PARSER_NAME = "xaj.xc.parse.Grm";
	
	public static final ID DESUGAR_PASS = new Pass.ID("desugar-pass");
	public static final ID FINISHED_DESUGAR_PASS = new Pass.ID(
			"finished-desugared-pass");
	//public static final ID DESUGAR_BUILD_TYPES = new Pass.ID("desugar-build-types-pass");

	public ExtensionInfo(Collection<String> jar_classes,
			Collection<String> aspect_sources) {
		super(jar_classes, aspect_sources);
	}

	static {
		// force Topics to load
		new Topics();
	}

	// Nome do compilador do xaj
	public String compilerName() {
		return "xajc";
	}

	// Retorna o parser do xaj
	public Parser parser(Reader reader, FileSource source, ErrorQueue eq) {
		//Lexer lexer = new Lexer_c(reader, source.path(), eq);
		Lexer lexer = new xaj.xc.parse.Lexer_c(reader, source.path(), eq);
		//Lexer lexer = new xaj.scc.parse.Lexer_c(reader, source.path(), eq);
		//Grm grm = new Grm(lexer, ts, nf, eq);	
		java_cup.runtime.lr_parser grm = null;
		try {		
			Class c;
			c = Class.forName(PARSER_NAME);
			
			Class conparam[] = new Class[4];
			conparam[0] = Lexer.class;
			conparam[1] = TypeSystem.class;
			conparam[2] = NodeFactory.class;
			conparam[3] = ErrorQueue.class;
			
			Constructor con = c.getConstructor(conparam);
			Object param[] = new Object[4];
			param[0] = lexer;
			param[1] = ts;
			param[2] = nf;
			param[3] = eq;
			
			Object o = con.newInstance(param);
			grm = (java_cup.runtime.lr_parser)o;
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
		}	
		return new CupParser(grm, source, eq);
	}

	// Retorna o fabrica de nó do xaj
	protected NodeFactory createNodeFactory() {
		return new XAJNodeFactory_c();
	}

	// Retorna o sistema de tipos do xaj
	protected TypeSystem createTypeSystem() {
		return new XAJTypeSystem_c();
	}

	
	public List<Pass> passes(Job job) { 
		List<Pass> passes =	super.passes(job);
		afterPass(passes, Pass.PARSE, new VisitorPass(DESUGAR_PASS, job,
		          new DesugarVisitor(job, typeSystem(),	nodeFactory())));
		afterPass(passes, DESUGAR_PASS, new	GlobalBarrierPass(FINISHED_DESUGAR_PASS, job));
		return passes;
	}
	 

	/*protected void passes_parse_and_clean(List<Pass> l, Job job) {
		super.passes_parse_and_clean(l, job);
		l.add(new VisitorPass(DESUGAR_PASS, job, new DesugarVisitor(job,
				typeSystem(), nodeFactory())));
		l.add(new GlobalBarrierPass(FINISHED_DESUGAR_PASS, job));

		// Fazer o passe TypeBuilder executar novamente para "setar"
		// os possível ponteiros nulos
		//Código copiado da classe abc.aspectj.ExtensionInfo
		l.add(new VisitorPass(Pass.BUILD_TYPES, job, new AJTypeBuilder(job, ts, nf)));
		//l.add(new GlobalBarrierPass(Pass.BUILD_TYPES_ALL, job));

	}*/
    protected Options createOptions() {
    	return new Options(this);
    }
}
